﻿using System;
using System.Collections;
using System.Collections.Generic;
using Test30.Core;
using Test30.Util;

namespace Test30.Engine
{
    public class EntityCollection : IEnumerable<Entity>
    {
        public readonly GameEvent<Entity, ValueChangeEventArgs<Vec>> EntityMoved = new GameEvent<Entity, ValueChangeEventArgs<Vec>>();
        public readonly GameEvent<Entity, ValueEventArgs<int>> EntityAdded = new GameEvent<Entity, ValueEventArgs<int>>();
        public readonly GameEvent<Entity, CollectionItemEventArgs<Entity>> EntityRemoved = new GameEvent<Entity, CollectionItemEventArgs<Entity>>();

        public Dungeon Dungeon { get; }
        public int Count => _entities.Count;
        public Entity this[int index] => _entities[index];

        public EntityCollection(Dungeon dungeon)
        {
            Dungeon = dungeon;
            _entities = new List<Entity>();
        }

        #region IEnumerable Members

        public IEnumerator<Entity> GetEnumerator()
        {
            return _entities.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        #region Collection api

        public void Add(Entity entity,int depth)
        {
            // add it to the collection and track its movement
            _entities.Add(entity);

            ((ICollectible<EntityCollection, Entity>)entity).SetCollection(this);

            EntityAdded.Raise(entity, new ValueEventArgs<int>(depth));

            // raise an event as if the entity just moved there
            EntityMoved.Raise(entity, new ValueChangeEventArgs<Vec>(entity.Position, entity.Position));
        }

        public void Clear()
        {
            _entities.Clear();
        }

        public void ForEach(Action<Entity> action)
        {
            _entities.ForEach(action);
        }

        public int IndexOf(Entity entity)
        {
            return _entities.IndexOf(entity);
        }

        public void Remove(Entity entity)
        {
            int index = IndexOf(entity);

            ((ICollectible<EntityCollection, Entity>)entity).SetCollection(null);

            _entities.Remove(entity);

            EntityRemoved.Raise(entity, new CollectionItemEventArgs<Entity>(entity, index));
        }

        #endregion

        private readonly List<Entity> _entities;
    }
}
